"""
RFQ控制器模块

该模块实现了RFQ（Radio Frequency Quadrupole）的核心控制功能，包括：
1. 系统状态管理：通过状态机实现不同运行状态之间的转换
2. 功率控制：实现自动功率加载和调节
3. 联锁管理：处理系统安全联锁
4. 真空监控：与真空系统集成，确保运行安全

主要组件：
- RFQController：核心控制器类，负责协调各个子系统
- 状态管理：通过状态模式实现不同运行状态
- PV管理：通过PVManager处理EPICS PV通信
- 真空监控：通过VacuumMonitor实现真空系统监控

使用示例：
    controller = RFQController(pre_para, pv_dict)
    while True:
        controller.update()
"""

from typing import Dict, Any
import time
from datetime import datetime
from epics import PV  # 添加PV类型的导入
from ..utils.pv_manager import PVManager
from ..services.vacuum_monitor import VacuumMonitor
from .rfq_states import RFQState, IdleState, InitializingState, RunningState, ErrorState

class RFQController:
    """
    RFQ控制器类
    
    该类是RFQ系统的核心控制器，负责：
    1. 系统初始化和状态管理
    2. 功率自动加载控制
    3. 联锁状态监控和处理
    4. 真空系统监控
    5. 异常情况处理
    
    主要功能：
    - 初始化：系统参数配置和PV连接建立
    - 状态控制：通过状态机实现不同运行状态的管理
    - 功率调节：实现自动功率加载和微调
    - 安全保护：联锁状态监控和异常处理
    
    属性：
        init_status (bool): 系统初始化状态
        pv_manager (PVManager): PV管理器实例
        vacuum_monitor (VacuumMonitor): 真空监控器实例
        current_state (RFQState): 当前系统状态
        interlock (int): 联锁状态
        power_tuning (str): 功率调节方向
        drive_mode (str): 当前驱动模式 ('pulse' 或 'cw')
        reset_count (int): 异常复位次数计数器
    
    方法：
        check_conditions(): 检查系统运行条件
        init_llrf(): 初始化LLRF系统
        auto_load(): 执行自动功率加载
        update(): 更新系统状态
    """
    
    def __init__(self, pre_para: Dict[str, Any], pv_dict: Dict[str, str]):
        """
        初始化RFQ控制器
        
        Args:
            pre_para: 预设参数字典，包含系统运行所需的关键参数
                - openloop_init: 开环初始值
                - cavity_power_margin: 腔体功率裕度
                - cavity_vacuum_threshold: 腔体真空阈值
            pv_dict: PV配置字典，定义所有需要监控和控制的PV
        """
        self.init_status = False
        self.pv_manager = PVManager(pv_dict)
        self.vacuum_monitor = VacuumMonitor(
            self.pv_manager,
            float(pre_para['cavity_vacuum_threshold'])
        )
        
        # 初始化参数
        self.openloop_init = int(pre_para['openloop_init'])
        self.cavity_power_margin = float(pre_para['cavity_power_margin'])
        
        # 设置功率回调
        self.pv_manager.set_callback('cavity_power', self.on_cavity_power_change)
        self.pv_manager.set_callback('pulsecwmode', self.on_mode_change)
        
        # 等待PV连接
        if not self.pv_manager.wait_for_connection():
            raise ConnectionError("PV连接超时")
            
        self.init_status = True
        self.power_tuning = None
        self.interlock = 0
        self.drive_mode = 'pulse'  # 默认pulse模式
        self.reset_count = 0    # 初始化复位计数器
        
        # 初始化状态
        self.current_state: RFQState = IdleState(self)
        
    def check_conditions(self) -> bool:
        """
        检查系统运行条件
        
        检查系统是否满足运行条件，包括：
        1. 系统初始化状态
        2. 真空系统状态
        3. 联锁状态
        
        Returns:
            bool: 是否满足运行条件
                True: 满足所有运行条件
                False: 任一条件不满足
        """
        return (self.init_status and 
                self.vacuum_monitor.get_vacuum_status() == 1 and 
                self.interlock == 1)
        
    def is_initialized(self) -> bool:
        """
        检查系统是否初始化完成
        
        检查系统是否完成初始化，包括：
        1. 系统初始化状态
        2. 联锁状态
        
        Returns:
            bool: 是否初始化完成
                True: 系统已初始化且联锁正常
                False: 系统未初始化或联锁异常
        """
        return self.init_status and self.interlock == 1
        
    def check_error_resolved(self) -> bool:
        """
        检查错误是否已解决
        
        检查系统错误是否已解决，通过检查所有运行条件是否满足。
        
        Returns:
            bool: 错误是否已解决
                True: 所有运行条件满足，错误已解决
                False: 仍有运行条件不满足，错误未解决
        """
        return self.check_conditions()
        
    def on_mode_change(self, data: Dict[str, Any]) -> None:
        """
        模式变化回调函数
        
        处理pulse/CW模式变化事件，更新当前驱动模式。
        
        Args:
            data: PV值变化数据，包含PV别名和新的值
        """
        if not self.init_status:
            return
            
        try:
            pulsecwmode_value = self.pv_manager.get_pv_value('pulsecwmode')
            self.drive_mode = 'cw' if pulsecwmode_value == 1 else 'pulse'
            print(f"当前驱动模式: {self.drive_mode}")
        except (KeyError, ValueError) as e:
            print(f"获取模式值失败: {str(e)}")
        
    def get_current_drive(self) -> PV:
        """
        获取当前模式的驱动PV
        
        Returns:
            PV: 当前模式对应的驱动PV对象
        """
        if self.drive_mode == 'cw':
            return self.pv_manager.get_pv('amplitude_cw_drive')
        else:
            return self.pv_manager.get_pv('amplitude_pulse_drive')
            
    def on_cavity_power_change(self, data: Dict[str, Any]) -> None:
        """
        腔体功率变化回调函数
        
        处理腔体功率变化事件，根据功率偏差决定调节方向。
        当功率偏差超过裕度时，设置相应的调节方向。
        
        处理流程：
        1. 检查系统初始化状态
        2. 获取当前功率相关PV值
        3. 计算功率偏差
        4. 设置调节方向
        
        Args:
            data: PV值变化数据，包含PV别名和新的值
        """
        if not self.init_status:
            return
            
        try:
            current_drive = self.get_current_drive()
            current_drive_value = current_drive.value
            cavity_power_value = self.pv_manager.get_pv_value('cavity_power')
            power_target_value = self.pv_manager.get_pv_value('powerTarget')
            
            if current_drive_value > 10:
                if abs(cavity_power_value - power_target_value) > self.cavity_power_margin:
                    if cavity_power_value > power_target_value:
                        self.power_tuning = "DECREASE"
                    elif cavity_power_value < power_target_value:
                        self.power_tuning = "INCREASE"
        except (KeyError, ValueError) as e:
            print(f"获取功率值失败: {str(e)}")
        
    def init_llrf(self) -> None:
        """
        初始化LLRF系统
        
        执行LLRF系统的初始化流程，包括：
        1. 联锁状态检查和复位
        2. RF系统启动
        3. 频率和功率初始化
        
        处理流程：
        1. 检查并处理联锁状态
        2. 检查并处理功率故障状态
        3. 启动RF系统
        4. 初始化频率和功率参数
        """
        arc_lock = self.pv_manager.get_pv('Arc_lock')                    # RFQ-LLRF:MC01:Arc_Lock
        interlock_status = self.pv_manager.get_pv('Interlock_status')    # RFQ-LLRF:MC01:Interlock_Status
        rf_pw_fail_status1 = self.pv_manager.get_pv('RFPWFailStatus1')  # RFQ-LLRF:MON01:RFPWFailStatus1
        rf_pw_fail_status2 = self.pv_manager.get_pv('RFPWFailStatus2')  # RFQ-LLRF:MON01:RFPWFailStatus2
        reset_interlock = self.pv_manager.get_pv('ResetInterlock')      # RFQ-LLRF:MC01:ResetInterlock
        reset_pw_fault_stat = self.pv_manager.get_pv('ResetPWFaultStat') # RFQ-LLRF:MON01:ResetPWFaultStat
        rf_on = self.pv_manager.get_pv('rf_on')                         # RFQ-LLRF:MC01:RFOn
        sweep_frequency = self.pv_manager.get_pv('sweep_frequency')     # RFQ-LLRF:MC01:sweepfrequency
        tracking_frequency_on = self.pv_manager.get_pv('tracking_frequency_on') # RFQ-LLRF:MC01:frequency_tracking
        
        # 检查并重置联锁
        if self.reset_count < 5:  # 只在复位次数小于5次时执行复位
            if arc_lock.value == 0 or interlock_status.value == 0:
                self.interlock = 0
                reset_interlock.value = 1
                time.sleep(0.5)
                reset_interlock.value = 0
                self.reset_count += 1
                print(f"执行联锁复位，当前复位次数: {self.reset_count}")
                
            if rf_pw_fail_status1.value == 0 and rf_pw_fail_status2.value == 0:
                self.interlock = 0
                reset_pw_fault_stat.value = 1
                time.sleep(0.5)
                reset_interlock.value = 0
                self.reset_count += 1
                print(f"执行功率故障复位，当前复位次数: {self.reset_count}")
        else:
            print("警告：异常复位次数已达到5次，请人工检查系统状态")
            return
            
        if (arc_lock.value == 1 and interlock_status.value == 1 and 
            rf_pw_fail_status1.value == 1 and rf_pw_fail_status2.value == 1):
            self.interlock = 1
            self.reset_count = 0  # 重置计数器，因为系统恢复正常
            
        # 启动RF
        if rf_on.value == 0 and self.interlock == 1:
            rf_on.value = 1
            print("开始加载RFQ功率")
            
        # 初始化频率和功率
        if (self.vacuum_monitor.get_vacuum_status() == 1 and rf_on.value == 1):
            if sweep_frequency.value == 0:
                sweep_frequency.value = 1
            if tracking_frequency_on.value == 0:
                tracking_frequency_on.value = 1
                
            current_drive = self.get_current_drive()
            if current_drive.value < 1:
                current_drive.value = self.openloop_init
                print(f"RFQ初始化成功，当前模式: {self.drive_mode}")
                
    def auto_load(self) -> None:
        """
        自动加载控制
        
        执行自动功率加载控制，根据功率调节方向调整驱动幅度。
        功率调节步长根据与目标功率的偏差动态调整：
        - 偏差 > 50%: 步长 = 20
        - 偏差 > 30%: 步长 = 10
        - 偏差 > 10%: 步长 = 5
        - 偏差 <= 10%: 步长 = 2
        
        处理流程：
        1. 检查PV连接状态
        2. 根据调节方向调整功率
        3. 记录操作日志
        
        功率调节规则：
        - 增加功率：根据偏差动态调整步长
        - 减少功率：每次减少5个单位（无量纲），最小值为0
        """
        if not self.pv_manager.check_connection():
            print("等待PV重新连接...")
            time.sleep(1)
            return
            
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        rf_on = self.pv_manager.get_pv('rf_on')                         # RFQ-LLRF:MC01:RFOn
        current_drive = self.get_current_drive()
        cavity_power = self.pv_manager.get_pv('cavity_power')           # RFQ-LLRF:MC01:rf3power
        power_target = self.pv_manager.get_pv('powerTarget')            # RFQ_RF:LLRF_01:PowTarg
        
        if (self.power_tuning == "INCREASE" and rf_on.value == 1 and 
            self.vacuum_monitor.get_vacuum_status() == 1):
            # 计算功率偏差百分比
            power_error = abs(cavity_power.value - power_target.value) / power_target.value * 100
            
            # 根据偏差确定步长
            if power_error > 50:
                step = 20
            elif power_error > 30:
                step = 10
            elif power_error > 10:
                step = 5
            else:
                step = 2
                
            current_drive.value += step
            print(f"{current_time}: 功率调节: 增加, 模式: {self.drive_mode}, 步长: {step}, 偏差: {power_error:.1f}%")
            time.sleep(1)
        elif (self.power_tuning == "DECREASE" and rf_on.value == 1 and 
              self.vacuum_monitor.get_vacuum_status() == 1):
            new_value = max(0, current_drive.value - 5)
            current_drive.value = new_value
            print(f"{current_time}: 功率调节: 减少, 模式: {self.drive_mode}, drive: {new_value}")
            time.sleep(1)
        else:
            time.sleep(1)
            
    def update(self) -> None:
        """
        更新系统状态
        
        执行状态机的更新操作，包括：
        1. 更新当前状态
        2. 处理状态转换
        3. 执行状态特定的操作
        
        状态转换流程：
        1. 调用当前状态的update方法
        2. 如果返回新状态，执行状态转换
        3. 调用新状态的enter方法
        """
        next_state = self.current_state.update()
        if next_state is not None:
            self.current_state.exit()
            self.current_state = next_state
            self.current_state.enter() 